/******************************************************************************/
/* TEST.INI: initialization file to test the debug functionality              */
/******************************************************************************/
/* This file is part of the uVision/ARM development tools.                    */
/* Copyright (c) 2012 Keil Software. All rights reserved.                     */
/* This software may only be used under the terms of a valid, current,        */
/* end user license from KEIL for a compatible version of KEIL software       */
/* development tools. Nothing else gives you the right to use this software.  */
/******************************************************************************/

// ensure logging into file is turned off
LOG OFF


/* The following debug functionality is tested: 
   - execution breakpoint with hit count
   - READ breakpoint
   - WRITE breakpoint
   - memory read
   - memory write
   - register read 
   - register write
   - Tstep
   - Go

The test is self-contained and can be executed on the hardware target

Test results get printed into a test log file. 
If the test is successful, all LEDS on the board are turned on.

To run the test on the target in batch mode:
1) connect TWR-K20 controller to USB (Serial DBG)
2) run uVision with the command line:
	uV4.exe -d Blinky.uvproj -t"DAP - Flash"
*/

// overall test success flag 
define int testSuccess;
testSuccess = 0;

// flags to show which particular tests are succeeded
define char bpExecSuccess;
bpExecSuccess = 0;

define char bpReadSuccess;
bpReadSuccess = 0;

define char bpWriteSuccess;
bpWriteSuccess = 0;

define char memReadSuccess;
memReadSuccess = 0;

define char memWriteSuccess;
memWriteSuccess = 0;

define char regReadSuccess;
regReadSuccess = 0;

define char regWriteSuccess;
regWriteSuccess = 0;

// function to read and write registers 

FUNC void RegReadWrite() {
	
	unsigned long VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9;
	unsigned long VR10, VR11, VR12, VR13, VR14, VR15, VxPSR;

	unsigned long VR_0, VR_1, VR_2, VR_3, VR_4, VR_5, VR_6, VR_7, VR_8, VR_9;
	unsigned long VR_10, VR_11, VR_12, VR_13, VR_14, VR_15, V_xPSR;
	
	unsigned long bogus;
	bogus = 0x0badF00D;

	printf("Register Read/Write started\n");


	// initialize temporary Variables with bogus Value
	VR0 = bogus;
	VR1 = bogus;
	VR2 = bogus;
	VR3 = bogus;
	VR4 = bogus;
	VR5 = bogus;
	VR6 = bogus;
	VR7 = bogus;
	VR8 = bogus;
	VR9 = bogus;
	VR10 = bogus;
	VR11 = bogus;
	VR12 = bogus;
	VR13 = bogus;
	VR14 = bogus;
	VR15 = bogus;
	VxPSR = bogus;


	// read and save current register Values
	VR0 = R0;
	VR1 = R1;
	VR2 = R2;
	VR3 = R3;
	VR4 = R4;
	VR5 = R5;
	VR6 = R6;
	VR7 = R7;
	VR8 = R8;
	VR9 = R9;
	VR10 = R10;
	VR11 = R11;
	VR12 = R12;
	VR13 = R13;
	VR14 = R14;
	VR15 = R15;
	VxPSR = xPSR;

// print read register values
	printf("R0  =  0x%x\n", VR0 );
	printf("R1  =  0x%x\n", VR1 ); 
	printf("R2  =  0x%x\n", VR2 ); 
	printf("R3  =  0x%x\n", VR3 ); 
	printf("R4  =  0x%x\n", VR4 ); 
	printf("R5  =  0x%x\n", VR5 ); 
	printf("R6  =  0x%x\n", VR6 ); 
	printf("R7  =  0x%x\n", VR7 ); 
	printf("R8  =  0x%x\n", VR8 ); 
	printf("R9  =  0x%x\n", VR9 ); 
	printf("R10 =  0x%x\n", VR10 );
	printf("R11 =  0x%x\n", VR11 );
	printf("R12 =  0x%x\n", VR12 );
	printf("R13 =  0x%x\n", VR13 );
	printf("R14 =  0x%x\n", VR14 );
	printf("R15 =  0x%x\n", VR15 );
	printf("xPSR = 0x%x\n", VxPSR );


	// check if all Values differ from bogus Value
	regReadSuccess = 
		VR0 != bogus &&
		VR1 != bogus &&
		VR2 != bogus &&
		VR3 != bogus &&
		VR4 != bogus &&
		VR5 != bogus &&
		VR6 != bogus &&
		VR7 != bogus &&
		VR8 != bogus &&
		VR9 != bogus &&
		VR10 != bogus &&
		VR11 != bogus &&
		VR12 != bogus &&
		VR13 != bogus &&
		VR14 != bogus &&
		VR15 != bogus &&
		VxPSR != bogus;

	if(regReadSuccess == 0)
	{
		printf("Register read failed\n");
		return; // there is no reason to test write if read fails
	}
	else
		printf("Register read passed: %d\n", regReadSuccess);

	printf("Register write started\n");

	// fill all registers with bogus Value
	R0 = bogus;
	R1 = bogus;
	R2 = bogus;
	R3 = bogus;
	R4 = bogus;
	R5 = bogus;
	R6 = bogus;
	R7 = bogus;
	R8 = bogus;
	R9 = bogus;
	R10 = bogus;
	R11 = bogus;
	R12 = bogus;
	// register R13-R15 and xPSR on hardware do not accept 0x0badf00d, use 0x0 instead 
	R13 = 0x0;
	R14 = 0x0;
	R15 = 0x0;	
	xPSR = 0x0;	

	// read back into another array 
	VR_0 = R0;
	VR_1 = R1;
	VR_2 = R2;
	VR_3 = R3;
	VR_4 = R4;
	VR_5 = R5;
	VR_6 = R6;
	VR_7 = R7;
	VR_8 = R8;
	VR_9 = R9;
	VR_10 = R10;
	VR_11 = R11;
	VR_12 = R12;
	VR_13 = R13;
	VR_14 = R14;
	VR_15 = R15;
	V_xPSR = xPSR;

	// print the values again
	printf("R0  =  0x%x\n", VR_0 );
	printf("R1  =  0x%x\n", VR_1 ); 
	printf("R2  =  0x%x\n", VR_2 ); 
	printf("R3  =  0x%x\n", VR_3 ); 
	printf("R4  =  0x%x\n", VR_4 ); 
	printf("R5  =  0x%x\n", VR_5 ); 
	printf("R6  =  0x%x\n", VR_6 ); 
	printf("R7  =  0x%x\n", VR_7 ); 
	printf("R8  =  0x%x\n", VR_8 ); 
	printf("R9  =  0x%x\n", VR_9 ); 
	printf("R10 =  0x%x\n", VR_10 );
	printf("R11 =  0x%x\n", VR_11 );
	printf("R12 =  0x%x\n", VR_12 );
	printf("R13 =  0x%x\n", VR_13 );
	printf("R14 =  0x%x\n", VR_14 );
	printf("R15 =  0x%x\n", VR_15 );
	printf("xPSR = 0x%x\n", V_xPSR );


	// check if new Values are bogus
	regWriteSuccess = 
		VR_0 == bogus &&
		VR_1 == bogus &&
		VR_2 == bogus &&
		VR_3 == bogus &&
		VR_4 == bogus &&
		VR_5 == bogus &&
		VR_6 == bogus &&
		VR_7 == bogus &&
		VR_8 == bogus &&
		VR_9 == bogus &&
		VR_10 == bogus &&
		VR_11 == bogus &&
		VR_12 == bogus &&
		VR_13 == 0x0 &&
		VR_14 == 0x0 &&
		VR_15 == 0x0 && 
		V_xPSR == 0x0;


	if(regWriteSuccess == 0)
	{
		printf("Register write failed\n");
	}
	else 
		printf("Register write passed: %d\n", regWriteSuccess);

	// write saved values back into registers
	// values are required to be written correctly for the rest of the register test to run properly
	R0 = VR0;
	R1 = VR1;
	R2 = VR2;
	R3 = VR3;
	R4 = VR4;
	R5 = VR5;
	R6 = VR6;
	R7 = VR7;
	R8 = VR8;
	R9 = VR9;
	R10 = VR10;
	R11 = VR11;
	R12 = VR12;
	R13 = VR13;
	R14 = VR14;
	R15 = VR15;
	xPSR = VxPSR;
	printf("Register read/write completed\n");
	
}


// function write predefined numbers into test_array1
FUNC void MemWrite(unsigned long address)   {
	unsigned int i;
	unsigned int val;
	printf("Memory write started\n");
	val = 0x1000;
	for(i = 0; i < 256; i++)
	{
		_WWORD(address, val);
		val++;
		address+=4;
	}
	printf("Memory write completed\n");
}

// function to read from test_array2 and check if write and read was successful
FUNC void MemRead(unsigned long address)   {
	unsigned int i;
	unsigned int val, v;

	printf("Memory read started\n");
	val = 0x1000;
	memReadSuccess = 1;	 // assume it is true
	for(i = 0; i < 256; i++)
	{
		v = _RWORD(address);
		if(v != val )
		{
			memReadSuccess = 0;
		}
		val++;
		address+=4;
	}
	printf("Memory read completed:\t%d\n", memReadSuccess);
}


Func void CheckBpExec()
{
	// PC should be 0x000006AE and value of bpTestCounter variable == 4

	if( R15 == 0x000006E8 && `bpTestCounter == 4 )
		  bpExecSuccess = 1;
    printf("Execution breakpoint (%d) :\t%d\n", `bpTestCounter, bpExecSuccess);
}

Func void CheckBpRead()
{
	// PC should be 0x00000776

	if( R15 == 0x00000708 && R1 == 0)
		  bpReadSuccess = 1;
    printf("Read breakpoint:\t %d\n", bpExecSuccess);
}


Func void CheckBpWrite()
{
	// PC should be 0x0000077C for simulator or 0x000007C4 for flash

	if(R15 == 0x0000074e)
		bpWriteSuccess = 1;
	else
		bpWriteSuccess = 0;
    printf("Execution breakpoint: %d\n", bpExecSuccess);	
}



FUNC void EvalSuccess()  {

   char success;
   unsigned int led1;
   unsigned int led2;
   success = 	testSuccess == 1 &&   	
   				bpExecSuccess && bpReadSuccess && bpWriteSuccess &&
				regReadSuccess && regWriteSuccess && 
				memReadSuccess && memWriteSuccess;

  exec ("LOG >.\\Flash.test_results");

  if (success == 1)  
  {
	  printf("Test passed\n");
  } 
  else 
  {
	  printf("Test failed\n");
  }
  
  // print test results to log file and turn on corresponding LED
  led1 = 0;
  led2 = 0;
  printf("Individual test results:\n");
  printf("Execution breakpoint:\t");
  if(bpExecSuccess)
  {
    printf("passed\n");
	led1 |= `led_mask[0];
  }
  else
    printf("failed\n");

  printf("Read breakpoint:\t");
  if(bpReadSuccess)
  {
    printf("passed\n");
	led1 |= `led_mask[1];
  }
  else
    printf("failed\n");

  printf("Write breakpoint:\t");
  if(bpWriteSuccess)
  {
    printf("passed\n");
	led1 |= `led_mask[2];
  }
  else
    printf("failed\n");
  
  printf("Register read:\t\t");
  if(regReadSuccess)
  {
    printf("passed\n");
	led2 |= `led_mask[3];
  }
  else
    printf("failed\n");

  printf("Register write:\t\t");
  if(regWriteSuccess)
  {
    printf("passed\n");
	led2 |= `led_mask[4];
  }
  else
    printf("failed\n");


  printf("Memory read:\t\t");
  if(memReadSuccess)
  {
    printf("passed\n");
	led2 |= `led_mask[5];
  }
  else
    printf("failed\n");

  printf("Memory write:\t\t");
  if(memWriteSuccess)
  {
    printf("passed\n");
	led2 |= `led_mask[6];
  }
  else
    printf("failed\n");

  printf("Test control flow:\t");
  if(testSuccess)
  {
    printf("passed\n");
	led2 |= `led_mask[7];
  }
  else
    printf("failed\n");

// lit the LEDs by writing to corresponding memory
	//_WWORD(`pin1_addr, led1);
	//_WWORD(`pin2_addr, led2);

  exec ("LOG OFF");
}


FUNC void OpenLog()
{
  exec ("LOG >.\\Flash.log");
}


BK * // remove all existing breakpoints

OpenLog();

// set execution breakpoint in LED_On with hit count == 4
BS \Blinky.c\97, 4
G // run to break point
// we are here when the breakpoint is hit
CheckBpExec();

BK *
// modify memory to change execution flow
E INT &reg_test=1
// set an access breakpoint in completion code 
BS READ test_success
G
CheckBpRead();


// test memory write -- fill in test_array1 with values
MemWrite(&test_array1[0]);

// test register read and write 
RegReadWrite();
// modify R1 register to set completion code to 2
R1=R1+2;
BS WRITE test_success

// step 6 times to skip first assignment 
T 6
// modify R2 register to set n to 256 (used for memory read/write check)
R2 = 256;
G
CheckBpWrite();


// at this point memory evaluation has been done by the application already
memWriteSuccess = `mem_write_success;
// test memory read 
MemRead(&test_array2[0]);
testSuccess = `test_success;
printf("Test completed, success = %d\n", testSuccess);

LOG OFF

// finally tests all flags and decide if test was successful
EvalSuccess()

EXIT
